package com.plus.config.dataEncry;

import com.plus.utils.AESUtil;
import lombok.AllArgsConstructor;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.nio.charset.Charset;

/**
 * @Description:前置请求解密处理
 */
@Order(1)
@ControllerAdvice
public class MyRequestBodyAdvice implements RequestBodyAdvice {


    @Override
    public boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
        SafetyProcess process = methodParameter.getMethodAnnotation(SafetyProcess.class);
        //如果带有安全注解且标记为解密，测进行解密操作
        return null != process && process.requestDecode();
    }

    /**
     * 约定，请求方解密算法：
     * 1.获取源字符串
     * 2.进行ase解密
     * 3.封装可重复读的请求流对象
     * @param httpInputMessage
     * @param methodParameter
     * @param type
     * @param aClass
     * @return
     * @throws IOException
     */
    @Override
    public HttpInputMessage beforeBodyRead(HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type,
                                           Class<? extends HttpMessageConverter<?>> aClass) throws IOException {
        HttpHeaders headers = httpInputMessage.getHeaders();
        String bodyStr = StreamUtils.copyToString(httpInputMessage.getBody(), Charset.forName("utf-8"));
        //解密
        byte[] body = AESUtil.decodeByte(bodyStr);
        return new MyHttpInputMessage(headers, body);
    }

    @Override
    public Object afterBodyRead(Object o, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type,
                                Class<? extends HttpMessageConverter<?>> aClass) {
        return o;
    }

    @Override
    public Object handleEmptyBody(Object o, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type,
                                  Class<? extends HttpMessageConverter<?>> aClass) {
        return o;
    }

    /**
     * 自定义消息体，因为org.springframework.http.HttpInputMessage#getBody()只能调一次，所以要重新封装一个可重复读的消息体
     */
    @AllArgsConstructor
    public static class MyHttpInputMessage implements HttpInputMessage {
        private HttpHeaders headers;
        private byte[] body;
        @Override
        public InputStream getBody() throws IOException {
            return new ByteArrayInputStream(body);
        }
        @Override
        public HttpHeaders getHeaders() {
            return headers;
        }
    }

}
